<template>
    <view class="sel-seat">
        <!-- top -->
        <view class="seat-head">
            <text class="sh-title">{{ title }}</text>
            <text class="sh-info">{{ info }}</text>
            <text class="sh-info">{{ roomName }}</text>
        </view>
        <!-- main -->
        <view class="seat-main">
            <movable-area :style="'height:'+(seatRow*40+350)+'rpx;'" class="vm-area">
                <movable-view :style="'width: 750rpx;height:'+(seatRow*40+350)+'rpx;'" :inertia="true" :scale="true" :scale-min="0.95" :scale-max="2"
                    direction="all" @change="onMove" @scale="onScale">
                    <view class="sm-title">
                        <text class="text"></text>
                    </view>
                    <view class="sm-screen">
                        <text class="text">银幕中央</text>
                    </view>
                    <view class="sm-line-center"></view>
                    <!-- seat content -->
                    <view v-for="(item,index) in seatArray" :key="index" class="sm-cell" :style="'width:'+boxWidth+'px;height:'+seatSize+'px'">
                        <view v-for="(seat,col) in item" :key="col" class="dp-ib" :style="'width:'+seatSize+'px;height:'+seatSize+'px'" @click="handleChooseSeat(index,col)">
                            <image v-if="seat.type===0" class="sm-icon" src="https://hijinka.oss-cn-shanghai.aliyuncs.com/uploads/mall1/20220307/669dde5d9fe28a377c151cadecb8dd65.png"
                                mode="aspectFit"></image>
                            <image v-else-if="seat.type===1" class="sm-icon" src="https://hijinka.oss-cn-shanghai.aliyuncs.com/uploads/mall1/20220307/899c7f9e0365ce6d97f9d5fe89ffe878.png"
                                mode="aspectFit"></image>
                            <image v-else-if="seat.type===2" class="sm-icon" src="https://hijinka.oss-cn-shanghai.aliyuncs.com/uploads/mall1/20220307/123044531581e70133020f0265bcabb2.png"
                                mode="aspectFit"></image>
                        </view>
                    </view>
                    <view class="sm-line-index" :style="'left: '+(10-moveX/scale)+'px;'">
                        <text class="text" :style="'height:'+seatSize+'px;'" v-for="(m,mindex) in mArr" :key="mindex">{{m}}</text>
                    </view>
                </movable-view>
            </movable-area>
            <view class="fix-tips" v-if="showTis">
                <view class="v-tips">
                    <image :style="'width:'+seatSize+'px;height:'+seatSize+'px'" src="https://hijinka.oss-cn-shanghai.aliyuncs.com/uploads/mall1/20220307/669dde5d9fe28a377c151cadecb8dd65.png"
                        mode="aspectFit"></image>
                    <text class="text">可选</text>
                </view>
                <view class="v-tips">
                    <image :style="'width:'+seatSize+'px;height:'+seatSize+'px'" src="https://hijinka.oss-cn-shanghai.aliyuncs.com/uploads/mall1/20220307/123044531581e70133020f0265bcabb2.png"
                        mode="aspectFit"></image>
                    <text class="text">不可选</text>
                </view>
                <view class="v-tips">
                    <image :style="'width:'+seatSize+'px;height:'+seatSize+'px'" src="https://hijinka.oss-cn-shanghai.aliyuncs.com/uploads/mall1/20220307/899c7f9e0365ce6d97f9d5fe89ffe878.png"
                        mode="aspectFit"></image>
                    <text class="text">选中</text>
                </view>
            </view>
        </view>
        <!-- foot -->
        <view class="seat-foot">
            <view class="sf-recommend" v-if="SelectNum === 0">
                <text class="text">推荐选座</text>
                <view class="sfr-tag" v-for="num in Math.min(max, 6)" :key="num" @click="smartChoose(num+1)">
                    <text class="text">{{ num+1 }}人</text>
                </view>
            </view>
            <view class="sf-arselect" v-if="SelectNum !== 0">
                <text class="text">已选</text>
                <scroll-view scroll-x="true">
                    <view class="scr-wrap">
                        <view class="sfr-selt" v-for="(optItem,optindex) in optArr" :key="optItem.SeatCode" @click="handleChooseSeat(optItem.rowIndex, optItem.colIndex)">
                            <!-- <image src="/static/close.png" class="sfr-close"></image> -->
                            <view class="txt">
                                <text class="text">{{optItem.RowNum+'排'+optItem.ColumnNum+'座'}}</text>
                                <text class="price">￥{{ optItem.Price || '' }}</text>
                            </view>
                            <view class="sfr-close">X</view>
                        </view>
                    </view>
                </scroll-view>
            </view>
            <view class="f-btn" :class="{disabled: SelectNum === 0 }" @click="buySeat">
                <text class="text">{{SelectNum === 0 ? '请选座位' : `确认座位`}}</text>
            </view>
        </view>
    </view>
</template>

<script>
export default {
    name: "anil-seat",
    props: {
        seatData: {
            type: Array
        },
        max: {
            type: Number,
            default: 4
        },
        title: {
            type: String,
            default: ''
        },
        info: {
            type: String,
            default: ''
        },
        roomName: {
            type: String,
            default: ''
        }
    },
    data() {
        return {
            scaleMin: 1,//h5端为解决1无法缩小问题，设为0.95
            boxWidth: 400, //屏幕宽度px
            space: ' ', //空格
            seatArray: [], //影院座位的二维数组,-1为非座位，0为未购座位，1为已选座位(绿色),2为已购座位(红色),一维行，二维列
            seatRow: 0, //影院座位行数
            seatCol: 0, //影院座位列数
            seatSize: 0, //座位尺寸
            SelectNum: 0, //选择座位数
            moveX: 0, //水平移动偏移量
            scale: 1, //放大倍数
            minRow: 0, //从第几行开始排座位
            minCol: 0, //从第几列开始排座位
            showTis: true, //显示选座提示
            seatList: [], //接口获取的原始位置
            mArr: [], //排数提示
            optArr: [], //选中的座位数组。
            isWXAPP: false,
        };
    },
    computed: {
        aPrice() {
            let totalAmount = ''
            if (this.optArr && this.optArr.length) {
                totalAmount = this.optArr.map(item => Number(item.Price)).reduce((prev, curr) => prev + curr)
            }
            return totalAmount
        },
        rpxNum() {
            return this.boxWidth / 750
        },
        pxNum() {
            return 750 / this.boxWidth
        },
    },
    watch: {
        seatData(newName, oldName) {
            if (newName.length > 0) {
                this.initData()
            }
        }
    },
    created() {
        // console.log("执行到了啊啊啊啊")
        //获取宽度
        uni.getSystemInfo({
            success: (e) => {
                this.boxWidth = e.screenWidth
                //#ifdef H5
                this.scaleMin = 0.95
                //#endif
            }
        })

    },
    methods: {
        initData: function () {
            this.$loading()
            let arr = this.seatData
            //假数据说明：SeatCode座位编号，RowNum-行号，ColumnNum-纵号，YCoord-Y坐标，XCoord-X坐标，Status-状态
            let row = 0
            let col = 0
            let minCol = parseInt(arr[0].XCoord)
            let minRow = parseInt(arr[0].YCoord)
            for (let i of arr) {
                minRow = parseInt(i.YCoord) < minRow ? parseInt(i.YCoord) : minRow
                minCol = parseInt(i.XCoord) < minCol ? parseInt(i.XCoord) : minCol
                row = parseInt(i.YCoord) > row ? parseInt(i.YCoord) : row
                col = parseInt(i.XCoord) > col ? parseInt(i.XCoord) : col
            }
            this.seatList = arr
            console.log(this.seatList, "this.seatList")
            this.seatRow = row - minRow + 1
            this.seatCol = col - minCol + 3
            this.minRow = minRow
            this.minCol = minCol - 1
            this.initSeatArray()
            this.$hideLoading()
        },
        //初始座位数组
        initSeatArray: function () {
            let seatArray = Array(this.seatRow).fill(0).map(() => Array(this.seatCol).fill({
                type: -1,
                SeatCode: '',
                RowNum: '',
                ColumnNum: ''
            }));
            this.seatArray = seatArray
            this.seatSize = this.boxWidth > 0 ?
                parseInt(parseInt(this.boxWidth, 10) / (this.seatCol + 1), 10) :
                parseInt(parseInt(414, 10) / (this.seatCol + 1), 10)
            this.initNonSeatPlace();
        },
        //初始化是座位的地方
        initNonSeatPlace: function () {
            let seat = this.seatList.slice()
            let arr = this.seatArray.slice()
            for (let num in seat) {
                let status = 2 //-1为非座位，0为未购座位，1为已选座位(绿色),2为已购座位(红色)
                if (seat[num].Status === 0) {
                    status = 0
                } else if (seat[num].Status === -1) {
                    status = -1
                }
                arr[parseInt(seat[num].YCoord) - this.minRow][parseInt(seat[num].XCoord) - this.minCol] = {
                    type: status,
                    SeatCode: seat[num].SeatCode,
                    RowNum: seat[num].RowNum,
                    ColumnNum: seat[num].ColumnNum,
                    Price: seat[num].Price,
                    status: seat[num].Status == 0 ? "N" : "LK",
                    name: seat[num].seatName,
                    area: seat[num].area,
                    love_status: seat[num].love_status,
                    real_price: seat[num].real_price,
                    // real_price: 0.0125  
                    //测试0.01支付
                }
            }
            this.seatArray = arr.slice()
            let mArr = []
            for (let i in arr) {
                let m = ''
                for (let n of arr[i]) {
                    if (n.SeatCode) {
                        m = n.RowNum
                    }
                }
                if (m) {
                    mArr.push(m)
                } else {
                    mArr.push('')
                }
            }
            this.mArr = mArr
        },
        //放大缩小事件
        onScale: function (e) {
            this.showTis = false
            // this.moveX=-e.detail.x
            let w = this.boxWidth * 0.5
            let s = 1 - e.detail.scale
            this.moveX = w * s
            this.scale = e.detail.scale
            if (s > 0 || s === 0) {
                this.showTis = true
            }
        },
        //移动事件
        onMove: function (e) {
            this.showTis = false
            this.moveX = e.detail.x
        },
        //重置座位
        resetSeat: function () {
            this.SelectNum = 0
            this.optArr = []
            //将所有已选座位的值变为0
            let oldArray = this.seatArray.slice();
            for (let i = 0; i < this.seatRow; i++) {
                for (let j = 0; j < this.seatCol; j++) {
                    if (oldArray[i][j].type === 1) {
                        oldArray[i][j].type = 0
                    }
                }
            }
            this.seatArray = oldArray;
        },
        //选定且购买座位
        buySeat: function () {
            if (this.SelectNum === 0) return;
            let oldArray = [];
            for (let i = 0; i < this.seatRow; i++) {
                for (let j = 0; j < this.seatCol; j++) {
                    if (this.seatArray[i][j].type === 1) {
                        oldArray.push(this.seatArray[i][j])
                    }
                }
            }
            console.log(this.optArr, "this.optArrthis.optArr")
            this.$emit('confirm', this.optArr)
        },
        //处理座位选择逻辑
        handleChooseSeat: function (row, col) {
            console.log(row, col)
            let seatValue = this.seatArray[row][col].type;
            let newArray = this.seatArray;
            //如果是已购座位，直接返回
            if (seatValue === 2 || seatValue === -1) return
            //如果是已选座位点击后变未选
            if (seatValue === 1) {
                newArray[row][col].type = 0
                this.SelectNum--
                this.getOptArr(newArray[row][col], 0)
            } else if (seatValue === 0) {
                if (this.SelectNum >= this.max) {
                    return uni.showToast({
                        title: '一次最多选择' + this.max + '张',
                        icon: 'none'
                    })
                }
                newArray[row][col].rowIndex = row
                newArray[row][col].colIndex = col
                newArray[row][col].type = 1
                this.SelectNum++
                this.getOptArr(newArray[row][col], 1)
            }
            //必须整体更新二维数组，Vue无法检测到数组某一项更新,必须slice复制一个数组才行
            this.seatArray = newArray.slice();
        },
        //处理已选座位数组
        getOptArr: function (item, type) {
            console.log(item, 111)
            let optArr = this.optArr
            if (type === 1) {
                optArr.push(item)
            } else if (type === 0) {
                let arr = []
                optArr.forEach(v => {
                    if (v.SeatCode !== item.SeatCode) {
                        arr.push(v)
                    }
                })
                optArr = arr
            }
            console.log(optArr, "optArr")
            this.optArr = optArr.slice()
        },
        //推荐选座,参数是推荐座位数目，
        smartChoose: function (num) {
            // console.log('num===', num)
            // 先重置
            this.resetSeat()
            //找到影院座位水平垂直中间位置的后一排
            let rowStart = parseInt((this.seatRow - 1) / 2, 10) + 1;
            //先从中间排往后排搜索
            let backResult = this.searchSeatByDirection(rowStart, this.seatRow - 1, num);
            if (backResult.length > 0) {
                this.chooseSeat(backResult);
                this.SelectNum += num
                return
            }
            //再从中间排往前排搜索
            let forwardResult = this.searchSeatByDirection(rowStart - 1, 0, num);
            if (forwardResult.length > 0) {
                this.chooseSeat(forwardResult);
                this.SelectNum += num
                return
            }
            //提示用户无合法位置可选
            // #ifdef H5
            this.$toast('无合法位置可选!')
            // alert()
            // #endif
        },

        //搜索函数,参数:fromRow起始行，toRow终止行,num推荐座位数
        searchSeatByDirection: function (fromRow, toRow, num) {
            /*
             * 推荐座位规则
             * (1)初始状态从座位行数的一半处的后一排的中间开始向左右分别搜索，取离中间最近的，如果满足条件，
             *    记录下该结果离座位中轴线的距离，后排搜索完成后取距离最小的那个结果座位最终结果，优先向后排进行搜索，
             *    后排都没有才往前排搜，前排逻辑同上
             *
             * (2)只考虑并排且连续的座位，不能不在一排或者一排中间有分隔
             *
             * */

            /*
             * 保存当前方向搜索结果的数组,元素是对象,result是结果数组，offset代表与中轴线的偏移距离
             * {
             *   result:Array([x,y])
             *   offset:Number
             * }
             *
             */
            let currentDirectionSearchResult = [];

            let largeRow = fromRow > toRow ? fromRow : toRow,
                smallRow = fromRow > toRow ? toRow : fromRow;

            for (let i = smallRow; i <= largeRow; i++) {
                //每一排的搜索,找出该排里中轴线最近的一组座位
                let tempRowResult = [],
                    minDistanceToMidLine = Infinity;
                for (let j = 0; j <= this.seatCol - num; j++) {
                    //如果有合法位置
                    if (this.checkRowSeatContinusAndEmpty(i, j, j + num - 1)) {
                        //计算该组位置距离中轴线的距离:该组位置的中间位置到中轴线的距离
                        let resultMidPos = parseInt((j + num / 2), 10);
                        let distance = Math.abs(parseInt(this.seatCol / 2) - resultMidPos);
                        //如果距离较短则更新
                        if (distance < minDistanceToMidLine) {
                            minDistanceToMidLine = distance;
                            //该行的最终结果
                            tempRowResult = this.generateRowResult(i, j, j + num - 1)
                        }
                    }
                }
                //保存该行的最终结果
                currentDirectionSearchResult.push({
                    result: tempRowResult,
                    offset: minDistanceToMidLine
                })
            }

            //处理后排的搜索结果:找到距离中轴线最短的一个
            //注意这里的逻辑需要区分前后排，对于后排是从前往后，前排则是从后往前找
            let isBackDir = fromRow < toRow;
            let finalReuslt = [],
                minDistanceToMid = Infinity;
            if (isBackDir) {
                //后排情况,从前往后
                currentDirectionSearchResult.forEach((item) => {
                    if (item.offset < minDistanceToMid) {
                        finalReuslt = item.result;
                        minDistanceToMid = item.offset;
                    }
                });
            } else {
                //前排情况，从后往前找
                currentDirectionSearchResult.reverse().forEach((item) => {
                    if (item.offset < minDistanceToMid) {
                        finalReuslt = item.result;
                        minDistanceToMid = item.offset;
                    }
                })
            }

            //直接返回结果
            return finalReuslt
        },

        /*辅助函数，判断每一行座位从i列到j列是否全部空余且连续
         *
         */
        checkRowSeatContinusAndEmpty: function (rowNum, startPos, endPos) {
            let isValid = true;
            for (let i = startPos; i <= endPos; i++) {
                if (this.seatArray[rowNum][i].type !== 0) {
                    isValid = false;
                    break;
                }
            }
            return isValid
        },
        //辅助函数：返回每一行的某个合理位置的座位数组
        generateRowResult: function (row, startPos, endPos) {
            let result = [];
            for (let i = startPos; i <= endPos; i++) {
                result.push([row, i])
            }
            return result
        },
        //辅助函数:智能推荐的选座操作
        chooseSeat: function (result) {
            let opt = this.optArr
            let oldArray = this.seatArray.slice();
            for (let i = 0; i < result.length; i++) {
                //选定座位
                oldArray[result[i][0]][result[i][1]].rowIndex = result[i][0]
                oldArray[result[i][0]][result[i][1]].colIndex = result[i][1]
                oldArray[result[i][0]][result[i][1]].type = 1
                this.optArr.push(oldArray[result[i][0]][result[i][1]])
            }
            this.seatArray = oldArray;
        },
    }
}
</script>

<style lang="scss">
.sel-seat {
  display: flex;
  flex-direction: column;
  width: 100%;
  height: 100vh;
  .seat-head {
    background-color: #ffffff;
    display: flex;
    flex-direction: column;
    padding: 20rpx 30rpx;
    position: relative;
    z-index: 5;
    .sh-title {
      font-size: 32rpx;
      font-weight: bold;
      color: #333333;
    }
    .sh-info {
      font-size: 24rpx;
      color: #999999;
      margin-top: 10rpx;
    }
  }
  .seat-main {
    width: 100%;
    position: relative;
    padding: 10rpx;
    .vm-area {
      width: 750rpx;
    }
    .sm-title {
      background-color: #dddddd;
      width: 380rpx;
      height: 34rpx;
      transform: perspective(34rpx) rotateX(-10deg);
      margin: 0 auto;
      display: flex;
      align-items: center;
      justify-content: center;
      position: relative;
      z-index: 2;
      .text {
        font-size: 24rpx;
        color: #333333;
      }
    }
    .sm-screen {
      width: 100rpx;
      height: 30rpx;
      border: 1rpx solid #cccccc;
      display: flex;
      align-items: center;
      justify-content: center;
      margin: 48rpx auto 0;
      border-radius: 4rpx;
      position: relative;
      z-index: 1;
      .text {
        font-size: 20rpx;
        color: #999999;
      }
    }
    .sm-line-center {
      height: 610rpx;
      width: 0;
      border: 1rpx dashed #e5e5e5;
      position: fixed;
      left: 50%;
      top: 0;
      display: block;
      z-index: 0;
      transform: translateX(-50%);
    }
    .fix-tips {
      display: flex;
      align-items: center;
      justify-content: center;
      font-size: 24rpx;
      position: fixed;
      bottom: 214rpx;
      left: 0;
      width: 100%;
      z-index: 1;
      padding: 20rpx;
      .v-tips {
        display: flex;
        align-items: center;
        color: #999;
        margin: 0 10rpx;
        .text {
          margin-left: 10rpx;
        }
      }
    }
    // seat style
    .sm-cell {
      display: flex;
      margin-top: 20rpx;
      align-items: center;
      justify-content: center;
      position: relative;
      z-index: 2;
      .sm-icon {
        width: 100%;
        height: 100%;
      }
    }
    .sm-line-index {
      position: fixed;
      top: 114rpx;
      left: 20rpx;
      border-radius: 14rpx;
      overflow: hidden;
      background-color: rgba($color: #000000, $alpha: 0.3);
      z-index: 3;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      padding-bottom: 20rpx;
      width: 30rpx;
      .text {
        font-size: 24rpx;
        color: #ffffff;
        width: 100%;
        text-align: center;
        margin-top: 20rpx;
      }
    }
  }
  .seat-foot {
    margin-top: auto;
    background-color: #ffffff;
    padding: 20rpx 30rpx;
    position: relative;
    z-index: 5;
    .sf-recommend {
      display: flex;
      align-items: center;
      justify-content: center;
      padding-bottom: 20rpx;
      .text {
        font-size: 28rpx;
        color: #666666;
      }
      .sfr-tag {
        width: 110rpx;
        height: 60rpx;
        border-radius: 4rpx;
        border: 1rpx solid #ccc;
        display: flex;
        align-items: center;
        justify-content: center;
        margin-left: 20rpx;
      }
    }
    .sf-arselect {
      @extend .sf-recommend;
      .text {
        font-size: 24rpx;
        color: #666666;
      }
      .price {
        font-size: 20rpx;
        color: red;
      }
      .scr-wrap {
        display: flex;
        white-space: nowrap;
      }
      .sfr-selt {
        // min-width: 130rpx;
        height: 60rpx;
        border-radius: 4rpx;
        border: 1rpx solid #ccc;
        display: flex;
        align-items: center;
        margin-left: 20rpx;
        position: relative;
        // margin-left: 20rpx;
        padding-left: 10rpx;
        padding-right: 10rpx;
        .txt {
          text {
            display: block;
          }
        }
        .sfr-close {
          // position: absolute;
          // right: 6rpx;
          // top: 10rpx;
          font-size: 26rpx;
          color: #999;
          margin-left: 10rpx;
        }
      }
    }
    .f-btn {
      background-color: #f45664;
      width: 100%;
      height: 90rpx;
      line-height: 90rpx;
      text-align: center;
      border-radius: 10rpx;
      .text {
        color: #ffffff;
        font-size: 36rpx;
      }
      &.disabled {
        opacity: 0.8;
      }
    }
  }
}
</style>
